package com.file.manage.controller;


import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.file.manage.domain.data.FileTreeDTO;
import com.file.manage.domain.data.FileVO;
import com.file.manage.domain.entity.File;
import com.file.manage.domain.enums.FileType;
import com.file.manage.domain.request.FileCopyMoveRequest;
import com.file.manage.domain.response.UploadTmpFileResponse;
import com.file.manage.domain.service.FileService;
import com.file.manage.infrastructure.base.CommonResult;
import com.file.manage.infrastructure.utils.TreeUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @since 2025-05-22
 */
@RestController
@RequestMapping("file")
@Tag(name = "文件管理")
@Slf4j
public class FileController {
    @Resource
    private FileService fileService;

    @Operation(summary = "新建文件夹")
    @GetMapping(value = "/createFolder")
    public CommonResult<?> createFolder(@RequestParam(value = "name") String name, @RequestParam(value = "parentId", required = false) String parentId) {
        fileService.createFolder(name, parentId);
        return CommonResult.success();
    }

    @Operation(summary = "修改文件夹名称")
    @GetMapping(value = "/updateNameById")
    public CommonResult<?> updateNameById(@RequestParam(value = "id") String id, @RequestParam(value = "name") String name) {
        fileService.updateNameById(id, name);
        return CommonResult.success();
    }

    @Operation(summary = "文件路径上传文件")
    @RequestMapping(value = "/uploadFileByFolders", method = RequestMethod.POST)
    public CommonResult<?> uploadFileByFolders(@RequestParam(value = "folders") List<String> folders, @RequestParam(value = "name") String name, MultipartFile multipartFile) {
        try {
            fileService.uploadFileByFolders(folders, name, multipartFile);
            return CommonResult.success();
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage(), e);
            return CommonResult.failed("文件上传失败");
        }
    }

    @Operation(summary = "父级id上传文件")
    @PostMapping(value = "/uploadFileByParentId")
    public CommonResult<?> uploadFileByParentId(@RequestParam(value = "parentId") String parentId, @RequestParam(value = "name") String name, @RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        try {
            fileService.uploadFileByParentId(parentId, name, multipartFile);
            return CommonResult.success();
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage(), e);
            return CommonResult.failed("文件上传失败");
        }
    }

    @Operation(summary = "上传临时文件")
    @RequestMapping(value = "/uploadTmpFile", method = RequestMethod.POST)
    public CommonResult<UploadTmpFileResponse> uploadTmpFile(@RequestParam(value = "folders") List<String> folders, @RequestParam(value = "name") String name, @RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        try {
            return CommonResult.success(fileService.uploadTmpFile(folders, name, multipartFile));
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage(), e);
            return CommonResult.failed("文件上传失败");
        }

    }

    @Operation(summary = "上传压缩包")
    @RequestMapping(value = "/uploadZip", method = RequestMethod.POST)
    public CommonResult<?> uploadZip(@RequestParam(value = "parentId", required = false) String parentId, @RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        try {
            fileService.uploadZip(parentId, multipartFile);
            return CommonResult.success();
        } catch (IOException e) {
            log.error("上传压缩包失败：{}", e.getMessage(), e);
            return CommonResult.failed("上传压缩包失败");
        }

    }


    @Operation(summary = "临时文件转为正式文件")
    @PostMapping(value = "/tmp2FormalFile")
    public CommonResult<?> tmp2FormalFile(@RequestBody List<UploadTmpFileResponse> responses) {
        try {
            fileService.tmp2FormalFile(responses);
        } catch (IOException e) {
            log.error("临时文件转为正式文件失败：{}", e.getMessage(), e);
            return CommonResult.failed("临时文件转为正式文件失败");

        }
        return CommonResult.success();
    }

    @Operation(summary = "通过父级id获取文件树")
    @GetMapping(value = "/selectTree")
    public CommonResult<List<FileTreeDTO>> selectTree(@RequestParam(value = "parentId", required = false) String parentId) {
        return CommonResult.success(fileService.selectTree(parentId));
    }

    @Operation(summary = "通过父级id获取子集所有文件")
    @GetMapping(value = "/selectChildrenAllFile")
    public CommonResult<List<FileTreeDTO>> selectChildrenAllFile(@RequestParam(value = "parentId", required = false) String parentId) {
        return CommonResult.success(TreeUtil.tree2List(fileService.selectTree(parentId)).stream().filter(t -> t.getType() == FileType.FILE).toList());
    }


    @Operation(summary = "通过父级id获取下级文件列表")
    @GetMapping(value = "/getByParentId")
    public CommonResult<List<FileVO>> getByParentId(@RequestParam(value = "parentId", required = false) String parentId) {
        return CommonResult.success(fileService.getByParentId(parentId));
    }

    @Operation(summary = "删除文件")
    @DeleteMapping(value = "/deleteById")
    public CommonResult<?> deleteById(@RequestParam(value = "id") String id) {
        fileService.deleteById(id);
        return CommonResult.success();
    }

    @Operation(summary = "锁定文件")
    @GetMapping(value = "/lock")
    public CommonResult<?> lock(@RequestParam(value = "id") String id) {
        fileService.lock(id);
        return CommonResult.success();
    }

    @Operation(summary = "解锁")
    @GetMapping(value = "/unlock")
    public CommonResult<?> unlock(@RequestParam(value = "id") String id) {
        fileService.unlock(id);
        return CommonResult.success();
    }

    @Operation(summary = "删除标记")
    @GetMapping(value = "/delTag")
    public CommonResult<?> delTag(@RequestParam(value = "id") String id) {
        fileService.delTag(id);
        return CommonResult.success();
    }

    @Operation(summary = "取消删除标记")
    @GetMapping(value = "/cancelDelTag")
    public CommonResult<?> cancelDelTag(@RequestParam(value = "id") String id) {
        fileService.cancelDelTag(id);
        return CommonResult.success();
    }


    @Operation(summary = "移动")
    @PostMapping(value = "/move")
    public CommonResult<?> move(@Valid @RequestBody FileCopyMoveRequest request) {
        fileService.move(request);
        return CommonResult.success();
    }

    @Operation(summary = "替换文件")
    @PostMapping(value = "/replaceFile")
    public CommonResult<?> replaceFile(@RequestParam(value = "id") String id, @RequestParam(value = "name") String name, MultipartFile multipartFilet) {
        try {
            fileService.replaceFile(id, name, multipartFilet);
            return CommonResult.success();
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage(), e);
            return CommonResult.failed("文件上传失败");
        }
    }

    @Operation(summary = "通过id集合下载文件", description = "文件id：拼接所有父级文件夹名称。文件夹id：以当前文件夹为根目录，保留文件夹路径，下载当前文件夹下所有文件夹与文件")
    @PostMapping(value = "/downLoadFileByIds")
    public void downLoadFileByIds(@RequestBody List<String> ids, HttpServletResponse response) {
        try {
            fileService.downLoadFileByIds(ids, response);
        } catch (Exception e) {
            log.error("下载失败", e);
            response.setContentType("application/json;charset=UTF-8");
            try (PrintWriter out = response.getWriter()) {
                out.write(JSONUtil.toJsonStr(e.getMessage()));
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    @Operation(summary = "通过id下载文件")
    @GetMapping(value = "/downLoadFile/{id}")
    public void downLoadFileById(@PathVariable(value = "id") String id, HttpServletResponse response) {
        try {
            id = id.contains(".") ? id.substring(0, id.lastIndexOf(".")) : id;
            File file = fileService.selectById(id);
            Assert.notNull(file, "文件不存在");
            fileService.downLoadFile(file.getFileUrl(), file.getName(), response, 0);
        } catch (Exception e) {
            log.error("下载失败", e);
            response.setContentType("application/json;charset=UTF-8");
            try (PrintWriter out = response.getWriter()) {
                out.write(JSONUtil.toJsonStr(e.getMessage()));
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    }

}
